﻿using QFramework;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;

public class CardSystem : AbstractSystem
{
    [Header("网格尺寸")]
    public int rows = 4;
    public int cols = 4;

    [Header("卡牌间距")]
    public float spacing = 1.5f;            // 行/列间距

    [Header("卡牌 Prefab / 数据")]
    public GameObject cardPrefab;
    public List<CardData> cardDatas = new List<CardData>();

    // ───────── 私有字段 ─────────
    private GameObject[] cards;
    private Transform cardParent;

    private readonly Queue<CardView> clickQueue = new Queue<CardView>();
    private readonly HashSet<CardView> queuedSet = new HashSet<CardView>();
    private bool isMatching = false;

    private int totalClickCount = 0;
    private float startTime = -1f;

    // 用来挂协程的 Mono
    private CoroutineHost coroutineHost;

    // ───────── 生命周期 ─────────
    protected override void OnInit()
    {
        // 协程宿主
        var hostGo = new GameObject("CardSystem_CoroutineHost");
        Object.DontDestroyOnLoad(hostGo);
        coroutineHost = hostGo.AddComponent<CoroutineHost>();

        // 卡牌父物体
        cardParent = new GameObject("CardMatrix").transform;

        GenerateCardMatrix();
    }

    protected override void OnDeinit()
    {
        ClearCards();

        if (coroutineHost) Object.Destroy(coroutineHost.gameObject);
        if (cardParent) Object.Destroy(cardParent.gameObject);
    }

    // ───────── 生成矩阵 ─────────
    public void GenerateCardMatrix()
    {
        if (!cardPrefab)
        {
            Debug.LogError("CardSystem: cardPrefab 未设置！");
            return;
        }

        if (rows <= 0 || cols <= 0)
        {
            Debug.LogError("CardSystem: 行列数必须 > 0");
            return;
        }

        coroutineHost.StopAllCoroutines();
        ClearCards();

        int totalSlots = rows * cols;
        if (totalSlots < 2)
        {
            Debug.LogError("卡牌数量太少，至少 2 张！");
            return;
        }

        if (cardDatas == null || cardDatas.Count == 0)
        {
            Debug.LogError("CardData 列表为空！");
            return;
        }

        // 准备配对后的随机卡牌数据
        List<CardData> prepared = PrepareCardData(totalSlots);

        cards = new GameObject[totalSlots];

        // 计算矩阵左上角（使整体以 (0,0) 居中）
        float width = (cols - 1) * spacing;
        float height = (rows - 1) * spacing;
        Vector2 origin = new Vector2(-width * 0.5f, height * 0.5f);

        int idx = 0;
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                if (idx >= prepared.Count) break;

                Vector3 pos = new Vector3(
                    origin.x + c * spacing,
                    origin.y - r * spacing,
                    0f);

                var go = Object.Instantiate(cardPrefab, pos, Quaternion.identity, cardParent);
                go.name = $"Card_{r}_{c}";
                cards[r * cols + c] = go;

                var view = go.GetComponent<CardView>();
                if (view)
                {
                    view.SetCardData(prepared[idx]);
                    view.OnCardClicked += OnCardClicked;
                }
                else
                {
                    Debug.LogError($"{go.name} 缺少 CardView 组件！");
                }

                idx++;
            }
        }
    }

    // ───────── 点击与匹配 ─────────
    public void OnCardClicked(CardView clicked)
    {
        if (clicked == null || clicked.IsMatched) return;
        if (queuedSet.Contains(clicked)) return;

        if (startTime < 0f) startTime = Time.time;
        totalClickCount++;

        queuedSet.Add(clicked);
        clickQueue.Enqueue(clicked);

        if (!isMatching)
            coroutineHost.StartCoroutine(CheckMatchCoroutine());
    }

    private IEnumerator CheckMatchCoroutine()
    {
        isMatching = true;

        while (clickQueue.Count >= 2)
        {
            yield return new WaitForSeconds(0.6f);

            var first = clickQueue.Dequeue();
            var second = clickQueue.Dequeue();
            queuedSet.Remove(first);
            queuedSet.Remove(second);

            if (!first || !second) continue;

            if (first.CardId == second.CardId)
            {
                first.MarkAsMatched();
                second.MarkAsMatched();
                CheckWin();
            }
            else
            {
                first.FlipBack();
                second.FlipBack();
            }
        }

        isMatching = false;

        if (clickQueue.Count >= 2)
            coroutineHost.StartCoroutine(CheckMatchCoroutine());
    }

    private void CheckWin()
    {
        foreach (var go in cards)
        {
            if (!go) continue;
            var view = go.GetComponent<CardView>();
            if (view && !view.IsMatched) return;
        }

        float elapsed = Time.time - startTime;
        Debug.Log($"🎉 胜利! 点击 {totalClickCount} 次, 用时 {elapsed:F2}s");

        var rm = this.GetSystem<ResultManager>();
        if (rm != null)
        {
            rm.StepCount = totalClickCount;
            rm.TimeTaken = elapsed;
        }

        SceneManager.LoadScene("Scores");
    }

    // ───────── 工具函数 ─────────
    private List<CardData> PrepareCardData(int totalSlots)
    {
        int pairCount = totalSlots / 2;
        var pool = cardDatas.Distinct().ToList();

        while (pool.Count < pairCount)
            pool.Add(pool[Random.Range(0, pool.Count)]);

        var selected = pool.GetRange(0, pairCount);

        var result = new List<CardData>(pairCount * 2);
        foreach (var data in selected)
        {
            result.Add(data);
            result.Add(data);
        }
        return Shuffle(result);
    }

    private static List<CardData> Shuffle(List<CardData> list)
    {
        for (int i = 0; i < list.Count; i++)
        {
            int j = Random.Range(i, list.Count);
            (list[i], list[j]) = (list[j], list[i]);
        }
        return list;
    }

    private class CoroutineHost : MonoBehaviour { }

    public void SetHosts(Transform parent, MonoBehaviour host)
    {
        cardParent = parent;
        coroutineHost = host as CoroutineHost ??
                        host.gameObject.AddComponent<CoroutineHost>();
    }

    private void ClearCards()
    {
        if (cards != null)
        {
            foreach (var go in cards)
            {
                if (!go) continue;
                var v = go.GetComponent<CardView>();
                if (v) v.OnCardClicked -= OnCardClicked;
                Object.Destroy(go);
            }
        }
        cards = null;
        clickQueue.Clear();
        queuedSet.Clear();
        isMatching = false;
        totalClickCount = 0;
        startTime = -1f;
    }
}
